#include "common.h"

int firstNoteFlag = 0;
unsigned char keyOffset = 0; //default scale will be in the key of C -> range of keyOffset is 0 - 11
int harmonizerScaleSelect = 0;
unsigned char Key;
unsigned int scaleLUT_Index;
int HarmonizerEffectOnFlag = 0;



/************** SCALES LUT *************************
****
** NOTES: if it works with one test scale it will work with all?
** Middle C is dec: 60, hex: 3C
*************************************************/
// the Japanese scale
unsigned char JAPANESE[55] = {0x37, //dec 55 -> size of array
	0x00,0x01,0x05,0x07,0x08, //Octave -1
	0x0C,0x0D,0x11,0x13,0x14, //Octave 0
	0x18,0x19,0x1D,0x1F,0x20, //Octave 1
	0x24,0x25,0x29,0x2B,0x2C, //Octave 2
	0x30,0x31,0x35,0x37,0x38, //Octave 3
	0x3C,0x3D,0x41,0x43,0x44, //Octave 4
	0x48,0x49,0x4D,0x4F,0x50, //Octave 5
	0x54,0x55,0x59,0x5B,0x5C, //Octave 6
	0x60,0x61,0x65,0x67,0x68, //Octave 7
	0x6C,0x6D,0x71,0x73,0x74, //Octave 8
	0x78,0x79,0x7D,0x7F}; //Octave 9 

unsigned char CHINESE[55] = {0x37, //dec 55 -> size of array
	0x00,0x02,0x04,0x07,0x09, //Octave -1
	0x0C,0x0E,0x10,0x13,0x15, //Octave 0
	0x18,0x1A,0x1C,0x1F,0x21, //Octave 1
	0x24,0x26,0x28,0x2B,0x2D, //Octave 2
	0x30,0x32,0x34,0x37,0x39, //Octave 3
	0x3C,0x3E,0x40,0x43,0x45, //Octave 4
	0x48,0x4A,0x4C,0x4F,0x51, //Octave 5
	0x54,0x56,0x58,0x5B,0x5D, //Octave 6
	0x60,0x62,0x64,0x67,0x69, //Octave 7
	0x6C,0x6E,0x70,0x73,0x75, //Octave 8
	0x78,0x7A,0x7C,0x7F}; //Octave 9 

// the Harmonic Minor scale
unsigned char HARMONIC_MINOR[76] = {0x4C, //dec 76 -> size of array
	0x00,0x02,0x03,0x05,0x07,0x08,0x0B, //Octave -1
	0x0C,0x0E,0x0F,0x11,0x13,0x14,0x17, //Octave 0
	0x18,0x1A,0x1B,0x1D,0x1F,0x20,0x23, //Octave 1
	0x24,0x26,0x27,0x29,0x2B,0x2C,0x2F, //Octave 2
	0x30,0x32,0x33,0x35,0x37,0x38,0x3B, //Octave 3
	0x3C,0x3E,0x3F,0x41,0x43,0x44,0x47, //Octave 4
	0x48,0x4A,0x4B,0x4D,0x4F,0x50,0x53, //Octave 5
	0x54,0x56,0x57,0x59,0x5B,0x5C,0x5F, //Octave 6
	0x60,0x62,0x63,0x65,0x67,0x68,0x6B, //Octave 7
	0x6C,0x6E,0x6F,0x71,0x73,0x74,0x77, //Octave 8
	0x78,0x7A,0x7B,0x7D,0x7F}; //Octave 9 

unsigned char CHROMATIC[128] = {0x7F,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B, //Octave -1
	0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, //Octave  0 
	0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23, //Octave  1 
	0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, //Octave  2
	0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B, //Octave  3 
	0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, //Octave  4 
	0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53, //Octave  5
	0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F, //Octave  6
	0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B, //Octave  7
	0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77, //Octave  8
	0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F }; //Octave 9 

// the WHITEKEYS values checked are db1 of a MIDI event
unsigned char WHITEKEYS[75] = {0x00,0x02,0x04,0x05,0x07,0x09,0x0B, //Octave -1
	0x0C,0x0E,0x10,0x11,0x13,0x15,0x17, //Octave 0
	0x18,0x1A,0x1C,0x1D,0x1F,0x21,0x23, //Octave 1
	0x24,0x26,0x28,0x29,0x2B,0x2D,0x2F, //Octave 2
	0x30,0x32,0x34,0x35,0x37,0x39,0x3B, //Octave 3
	0x3C,0x3E,0x40,0x41,0x43,0x45,0x47, //Octave 4
	0x48,0x4A,0x4C,0x4D,0x4F,0x51,0x53, //Octave 5
	0x54,0x56,0x58,0x59,0x5B,0x5D,0x5F, //Octave 6
	0x60,0x62,0x64,0x65,0x67,0x69,0x6B, //Octave 7
	0x6C,0x6E,0x70,0x71,0x73,0x75,0x77, //Octave 8
	0x78,0x7A,0x7C,0x7D,0x7F }; //Octave 9 


// the BLACKKEYS values checked are db1 of a MIDI event
unsigned char BLACKKEYS[53] = {0x01,0x03,0x06,0x08,0x0A, //Octave -1
	0x0D,0x0F,0x12,0x14,0x16, //Octave 0
	0x19,0x1B,0x1E,0x20,0x22, //Octave 1
	0x25,0x27,0x2A,0x2C,0x2E, //Octave 2
	0x31,0x33,0x36,0x38,0x3A, //Octave 3
	0x3D,0x3F,0x42,0x44,0x46, //Octave 4
	0x49,0x4B,0x4E,0x50,0x52, //Octave 5
	0x55,0x57,0x5A,0x5C,0x5E, //Octave 6
	0x61,0x63,0x66,0x68,0x6A, //Octave 7
	0x6D,0x6F,0x72,0x74,0x76, //Octave 8
	0x79,0x7B,0x7E }; //Octave 9 

/************** SCALES *************************
**
*************************************************/
unsigned char *harmonizerScales[NUMOFHARM_SCALES];    

void ScaleHarmonizer(MIDIEvent *event){
	unsigned char tempDB1,boundsCheck; 
	unsigned int index = 0;

	harmonizerScales[0] = CHROMATIC;
	harmonizerScales[1] = JAPANESE;
	harmonizerScales[2] = HARMONIC_MINOR;
	harmonizerScales[3] = CHINESE;

	if( event->db1 > 0x7F ){ event->db1 = 0x01;} //make it a black key which wont sound
	
	
	    if(harmonizerScales[harmonizerScaleSelect][0] != 0x7F){   //if we are using the Chromatic scale we dont care about this fn
			for(index = 0; index < NUM_BLCK_KEYS; index++){
				if(event->db1 == BLACKKEYS[index]){
					if (!firstNoteFlag) {
						//event->db1 = 0x01; //note 1 
						event->db2 = 0x01; //vel 1  -> no sound
					}
				}
			}
		
			if (firstNoteFlag) firstNoteFlag = 0;  //Can only change key when we turn effect OFF then ON
			
			
			tempDB1 = event->db1;
			for(index = 0; index < NUM_WHITE_KEYS; index++){
				if(tempDB1 == WHITEKEYS[index]){
					scaleLUT_Index = index; //use the index of found white key to play "correct" note in specified scale
					if(scaleLUT_Index < harmonizerScales[harmonizerScaleSelect][0]){ // < size of scale array 
						boundsCheck = harmonizerScales[harmonizerScaleSelect][scaleLUT_Index] + keyOffset;
						if( boundsCheck >  0x7F){event->db1 = 0x00; event->db2 = 0x00;}
					    else {event->db1 = harmonizerScales[harmonizerScaleSelect][scaleLUT_Index] + keyOffset;}
				    }else{event->db1 = 0x00; event->db2 = 0x00; } //default to note 0 velocity 0  //was 0x00
					
				         
			    }
			}
		//if(harmonizerScales[harmonizerScaleSelect][0] == 0x37){event->db1 = event->db1 - 23;}
	    }
	//event->db1 = event->db1 + keyOffset;
} 

//if(randArpHSnum >= 0){ event->db1 = keyOffset + (harmonizerScales[harmonizerScaleSelect][(scaleLUT_Index + (rand()%randArpHSnum))]);}
//else if(randArpHSnum < 0){ event->db1 = (event->db1 - (rand()%(-1*randArpHSnum)));	}
